#pragma once
#include <stdio.h>
#include <tchar.h>
#include <string>
#include <map>
#include <assert.h>
#include "ResourceCache.h"
#include "..\interfaces.h"
class Resource;


typedef std::map<std::string, int> ZipContentsMap;		// maps file location with an id
class ZipFile
{
public:
    ZipFile() { m_nEntries=0; m_pFile=NULL; m_pDirData=NULL; }
    virtual ~ZipFile() { 
	End();
	if(m_pFile)fclose(m_pFile); 
	}

    bool Init(const _TCHAR *resFileName);
    void End();

    int GetNumFiles()const { return m_nEntries; }
    void GetFilename(int i, char *pszDest) const;
    int GetFileLen(int i) const;
    bool ReadFile(int i, void *pBuf);

	int Find(const char *path) const;
	bool Exist(const char *path) const;
	ZipContentsMap m_ZipContentsMap;

	/////////////////////////////////////////////////
	//Member Vars
private:
    struct TZipDirHeader;
    struct TZipDirFileHeader;
    struct TZipLocalHeader;

    FILE *m_pFile;		// Zip file
    char *m_pDirData;	// Raw data buffer.
    int  m_nEntries;	// Number of entries.

    // Pointers to the dir entries in pDirData.
    const TZipDirFileHeader **m_papDir;   
};



class ResourceZipFile : public IResourceFile
{
public:
	ResourceZipFile(std::wstring location) 
	{ 
		m_FileName = location; m_file = NULL; 
		if(!VOpen())
		{
				std::wstring error_msg = _T("Could open open file with filename: ");
				error_msg.append(location);
				assert(0 && error_msg.c_str());
		}
	}
	~ResourceZipFile() {}

private:
	ZipFile * m_file;
	std::wstring m_FileName;
public:
	virtual bool VOpen() {
		m_file = RE_NEW ZipFile;
		if(m_file != NULL)
		{
			if(!m_file->Init(m_FileName.c_str()))
			{
				assert(0 && "Could not init the ZipFile instance.");
				return false;
			}
		}
		else 
			return false;
		return true;
	}
	virtual const std::string VGetFilename();
	virtual unsigned int VGetResourceSize(const Resource &res);
	virtual void VGetResource(const Resource &res, char * buffer);
	virtual bool VFileExist(const std::string & filename) { return m_file->Exist(filename.c_str()); };
};